﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using RhythmComet.Particles;

namespace RhythmComet.Physics
{
    public class DirectionalForce : IForce
    {
        float force;
        Vector2 direction;
        Vector2 acceleration;

        public DirectionalForce(float force, Vector2 direction)
        {
            this.force = force;
            this.direction = PhysicsHelper.NormalizaR2(direction);
            this.acceleration = this.direction * force;
        }

        public void Act(ref Vector2 Position, ref Vector2 Velocity, float dt)
        {
            Position.X = PhysicsHelper.FuncaoEspaco(Position.X, Velocity.X, this.acceleration.X, dt);
            Position.Y = PhysicsHelper.FuncaoEspaco(Position.Y, Velocity.Y, this.acceleration.Y, dt);

            Velocity.X = PhysicsHelper.FuncaoVelocidade(Velocity.X, this.acceleration.X, dt);
            Velocity.Y = PhysicsHelper.FuncaoVelocidade(Velocity.Y, this.acceleration.Y, dt);
        }
    }

    public class PunctualForce : IForce
    {
        float force;
        Vector2 center;

        public PunctualForce(float force, Vector2 center)
        {
            this.force = force;
            this.center = center;
        }

        public void Act(ref Vector2 Position, ref Vector2 Velocity, float dt)
        {
            Vector2 acceleration;
            Vector2 direction;
            float distance;

            distance = Math.Max(Vector2.Distance(Position, center), 1);

            if (distance < 3)
            {
                Velocity.X = 0.0f;
                Velocity.Y = 0.0f;
            }

            direction = PhysicsHelper.NormalizaR2(PhysicsHelper.Direcao(Position, this.center));

            acceleration = direction * (force/distance);

            Position.X = PhysicsHelper.FuncaoEspaco(Position.X, Velocity.X, acceleration.X, dt);
            Position.Y = PhysicsHelper.FuncaoEspaco(Position.Y, Velocity.Y, acceleration.Y, dt);

            Velocity.X = PhysicsHelper.FuncaoVelocidade(Velocity.X, acceleration.X, dt);
            Velocity.Y = PhysicsHelper.FuncaoVelocidade(Velocity.Y, acceleration.Y, dt);


            //para nao acelerar ate o infinito
            if (PhysicsHelper.NormaR2(Velocity) > 300)
            {
                Velocity = PhysicsHelper.NormalizaR2(Velocity) * 300;
            }

            //Velocity.X = Math.Min(PhysicsHelper.FuncaoVelocidade(Velocity.X, acceleration.X, dt), 100);
            //Velocity.Y = Math.Min(PhysicsHelper.FuncaoVelocidade(Velocity.Y, acceleration.Y, dt), 100);
        }
    }

    public class DirectionalForce3D : IForce3D
    {
        float force;
        Vector3 direction;
        Vector3 acceleration;

        public DirectionalForce3D(float force, Vector3 direction)
        {
            this.force = force;
            this.direction = PhysicsHelper.NormalizaR3(direction);
            this.acceleration = this.direction * force;
        }

        public void ApplyForce(ParticleCollection particles, int index, float dt)
        {
            Vector3 position = particles.GetPosition(index);
            Vector3 velocity = particles.GetVelocity(index);

            Vector3 direction = PhysicsHelper.NormalizaR3(-1 * velocity);

            //particles.SetPosition(index, new Vector3(
            //        PhysicsHelper.FuncaoEspaco(position.X, velocity.X, this.acceleration.X, dt),
            //        PhysicsHelper.FuncaoEspaco(position.Y, velocity.Y, this.acceleration.Y, dt),
            //        PhysicsHelper.FuncaoEspaco(position.Z, velocity.Z, this.acceleration.Z, dt)
            //    ));

            //particles.SetVelocity(index, new Vector3(
            //        PhysicsHelper.FuncaoVelocidade(velocity.X, this.acceleration.X, dt),
            //        PhysicsHelper.FuncaoVelocidade(velocity.Y, this.acceleration.Y, dt),
            //        PhysicsHelper.FuncaoVelocidade(velocity.Z, this.acceleration.Z, dt)
            //    ));

            particles.SetPosition(index, new Vector3(
                    PhysicsHelper.FuncaoEspaco(position.X, velocity.X, direction.X, dt),
                    PhysicsHelper.FuncaoEspaco(position.Y, velocity.Y, direction.Y, dt),
                    PhysicsHelper.FuncaoEspaco(position.Z, velocity.Z, direction.Z, dt)
                ));

            particles.SetVelocity(index, new Vector3(
                    PhysicsHelper.FuncaoVelocidade(velocity.X, direction.X, dt),
                    PhysicsHelper.FuncaoVelocidade(velocity.Y, direction.Y, dt),
                    PhysicsHelper.FuncaoVelocidade(velocity.Z, direction.Z, dt)
                ));
        }
    }
}
